home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GFX Sensations 1
/
Graphic Sensations - Volume 1.iso
/
tools
/
amiga
/
powerpak
/
ppdata
/
ppdata.c
next >
Wrap
C/C++ Source or Header
|
2000-01-01
|
10KB
|
342 lines
/********************************************************************
* *
* PowerPacker DATA file support function V1.1 *
* ------------------------------------------- *
* (Read Packer.doc for more information) *
* *
* error = PP_LoadData (file, col, typeofmem, buffer, length, pw) *
* with: *
* char *file; filename *
* UBYTE col; color (see ppdata.h) *
* ULONG typeofmem type of memory that will be allocated *
* UBYTE **buffer pointer to pointer to buffer *
* ULONG *length pointer to buffer length *
* char *pw; pointer to password or NULL *
* *
* NOTE: - After loading you must free the allocated memory: *
* DO NOT FORGET !!!!! *
* FreeMem (buffer, length); *
* - Errors are defined in ppdata.h *
* - For encrypted data call first with pw = NULL, then *
* if error is PP_CRYPTED you know file is crypted. *
* Prompt the user for a password and call again with *
* pw pointing to this password. If the password is *
* incorrect error is PP_PASSERR, otherwise the file will *
* be loaded and decrypted. *
* *
* Example: *
* *
* #include <ppdata.h> *
* ... *
* *
* UBYTE *mymem = NULL; *
* ULONG mylen = 0; *
* *
* err = PP_LoadData ("df0:myfile.pp", DECR_POINTER, *
* MEMF_PUBLIC+MEMF_CHIP, &mymem, &mylen, NULL); *
* if (err == PP_LOADOK) { *
* DoSomething (mymem, mylen); *
* FreeMem (mymem, mylen); *
* } *
* else switch (err) { *
* case PP_CRYPTED: *
* puts ("File is encrypted !"); *
* break; *
* case PP_READERR: *
* puts ("Loading error !!!"); *
* break; *
* ... *
* } *
* *
********************************************************************/
/********************************************************************
* *
* 'PP_LoadData' PowerPacker DATA file support function V1.1 *
* *
* You may use this code for non-commercial purposes provided this *
* copyright notice is left intact ! *
* *
* Copyright (c) Aug 1989 by Nico François *
********************************************************************/
#include <exec/types.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <functions.h>
#include <ppdata.h>
#define SAFETY_MARGIN 64L
#define SIZEOF (ULONG)sizeof
#define myRead(to,len) if (Read (pp_lock, to, len) != len) {\
pp_FreeStuff(); return (PP_READERR); }
struct FileLock *pp_lock;
struct FileInfoBlock *pp_FileInfoBlock;
UBYTE *pp_filestart;
ULONG pp_bufferlen;
UWORD pp_coladdr[4] = { 0xf180, 0xf182, 0xf1a2, 0xf102 };
UWORD pp_CalcCheckSum();
ULONG pp_CalcPasskey();
PP_LoadData (pp_file, color, typeofmem, buffer, length, pw) /* Version 1.1 */
char *pp_file;
UBYTE color;
ULONG typeofmem;
UBYTE **buffer;
ULONG *length;
char *pw;
{
ULONG hdr, pp_seek;
UWORD *decrcol, instr, hicol, locol, pp_passchecksum;
ULONG pp_filelen, pp_crunlen, pp_efficiency;
UBYTE pp_crunched, pp_crypt = FALSE;
extern void pp_DecrunchBuffer(), pp_DecrunchColor();
pp_filestart = NULL;
if (!(pp_FileInfoBlock = (struct FileInfoBlock *)AllocMem
(SIZEOF(*pp_FileInfoBlock), MEMF_PUBLIC))) return (PP_NOMEMORY);
/* Set decruncher color */
decrcol = (UWORD *)pp_DecrunchColor;
if (color != 4) {
instr = 0x33c9; hicol = 0x00df;
locol = pp_coladdr[color]; /* = move.w a1,$dff1xx */
}
else instr = hicol = locol = 0x4e71; /* nop */
*decrcol = instr;
*(decrcol+1) = hicol; *(decrcol+2) = locol;
if (!(pp_lock = (struct FileLock *)Lock (pp_file, ACCESS_READ))) {
pp_FreeStuff();
return (PP_LOCKERR);
}
Examine (pp_lock, pp_FileInfoBlock);
UnLock (pp_lock);
pp_crunlen = pp_FileInfoBlock->fib_Size;
/* read decrunched length */
if (!(pp_lock = (struct FileLock *)Open (pp_file, MODE_OLDFILE))) {
pp_FreeStuff();
return (PP_OPENERR);
}
myRead (&hdr, 4L);
/* check if crunched */
if ((hdr == 'PX20' || hdr == 'PP11' || hdr == 'PP20') && (pp_crunlen>16L)) {
if (hdr == 'PX20') {
if (!pw) {
pp_FreeStuff();
return (PP_CRYPTED);
}
myRead (&pp_passchecksum, 2L);
if (pp_CalcCheckSum (pw) != pp_passchecksum) {
pp_FreeStuff();
return (PP_PASSERR);
}
pp_crypt = TRUE;
pp_seek = 6L;
}
else pp_seek = 4L;
Seek (pp_lock, pp_crunlen - 4L, OFFSET_BEGINNING);
myRead (&pp_filelen, 4L);
pp_filelen >>= 8L;
pp_crunlen -= 4L + pp_seek;
Seek (pp_lock, pp_seek, OFFSET_BEGINNING);
myRead (&pp_efficiency, 4L);
pp_bufferlen = pp_filelen + SAFETY_MARGIN;
pp_crunched = TRUE;
}
else {
Seek (pp_lock, 0L, OFFSET_BEGINNING);
pp_bufferlen = pp_filelen = pp_crunlen;
pp_crunched = FALSE;
}
if (!(pp_filestart=(UBYTE *)AllocMem (pp_bufferlen, typeofmem))) {
pp_FreeStuff();
return (PP_NOMEMORY);
}
/* load file */
myRead (pp_filestart, pp_crunlen);
Close (pp_lock);
FreeMem (pp_FileInfoBlock, SIZEOF(*pp_FileInfoBlock));
if (pp_crunched) {
if (pp_crypt)
pp_Decrypt (pp_filestart, pp_crunlen-4L, pp_CalcPasskey (pw));
pp_DecrunchBuffer (pp_filestart + pp_crunlen,
pp_filestart + SAFETY_MARGIN, pp_efficiency);
FreeMem (pp_filestart, SAFETY_MARGIN);
pp_filestart += SAFETY_MARGIN;
}
*buffer = pp_filestart;
*length = pp_filelen;
return (PP_LOADOK);
}
pp_FreeStuff()
{
if (pp_lock) Close (pp_lock);
if (pp_filestart) FreeMem (pp_filestart, pp_bufferlen);
if (pp_FileInfoBlock) FreeMem (pp_FileInfoBlock, SIZEOF(*pp_FileInfoBlock));
}
#asm
;
; PowerPacker Decrunch assembler subroutine V1.1
;
; call as:
; DecrunchBuffer (endcrun, buffer, efficiency);
; with:
; endcrun : UBYTE * just after last byte of crunched file
; buffer : UBYTE * to memory block to decrunch in
; efficiency: Longword defining efficiency with wich file was crunched
;
; NOTE:
; Decrunch a few bytes higher (safety margin) than the crunched file
; to decrunch in the same memory space. (64 bytes suffice)
;
XDEF _pp_DecrunchBuffer
XDEF _pp_DecrunchColor
XDEF _pp_CalcCheckSum
XDEF _pp_CalcPasskey
XDEF _pp_Decrypt
_pp_DecrunchBuffer:
move.l 4(a7),a0
move.l 8(a7),a1
move.l 12(a7),d0
movem.l d1-d7/a2-a6,-(a7)
bsr.s Decrunch
movem.l (a7)+,d1-d7/a2-a6
rts
Decrunch:
lea myBitsTable(PC),a5
move.l d0,(a5)
move.l a1,a2
move.l -(a0),d5
moveq #0,d1
move.b d5,d1
lsr.l #8,d5
add.l d5,a1
move.l -(a0),d5
lsr.l d1,d5
move.b #32,d7
sub.b d1,d7
LoopCheckCrunch:
bsr.s ReadBit
tst.b d1
bne.s CrunchedBytes
NormalBytes:
moveq #0,d2
Read2BitsRow:
moveq #2,d0
bsr.s ReadD1
add.w d1,d2
cmp.w #3,d1
beq.s Read2BitsRow
ReadNormalByte:
move.w #8,d0
bsr.s ReadD1
move.b d1,-(a1)
dbf d2,ReadNormalByte
cmp.l a1,a2
bcs.s CrunchedBytes
rts
CrunchedBytes:
moveq #2,d0
bsr.s ReadD1
moveq #0,d0
move.b (a5,d1.w),d0
move.l d0,d4
move.w d1,d2
addq.w #1,d2
cmp.w #4,d2
bne.s ReadOffset
bsr.s ReadBit
move.l d4,d0
tst.b d1
bne.s LongBlockOffset
moveq #7,d0
LongBlockOffset:
bsr.s ReadD1
move.w d1,d3
Read3BitsRow:
moveq #3,d0
bsr.s ReadD1
add.w d1,d2
cmp.w #7,d1
beq.s Read3BitsRow
bra.s DecrunchBlock
ReadOffset:
bsr.s ReadD1
move.w d1,d3
DecrunchBlock:
move.b (a1,d3.w),d0
move.b d0,-(a1)
dbf d2,DecrunchBlock
EndOfLoop:
_pp_DecrunchColor:
move.w a1,$dff1a2
cmp.l a1,a2
bcs.s LoopCheckCrunch
rts
ReadBit:
moveq #1,d0
ReadD1:
moveq #0,d1
subq.w #1,d0
ReadBits:
lsr.l #1,d5
roxl.l #1,d1
subq.b #1,d7
bne.s No32Read
move.b #32,d7
move.l -(a0),d5
No32Read:
dbf d0,ReadBits
rts
myBitsTable:
dc.b $09,$0a,$0b,$0b
_pp_CalcCheckSum:
move.l 4(a7),a0
moveq #0,d0
moveq #0,d1
sumloop:
move.b (a0)+,d1
beq.s exitasm
ror.w d1,d0
add.w d1,d0
bra.s sumloop
_pp_CalcPasskey:
move.l 4(a7),a0
moveq #0,d0
moveq #0,d1
keyloop:
move.b (a0)+,d1
beq.s exitasm
rol.l #1,d0
add.l d1,d0
swap d0
bra.s keyloop
exitasm:
rts
_pp_Decrypt:
move.l 4(a7),a0
move.l 8(a7),d1
move.l 12(a7),d0
move.l d2,-(a7)
addq.l #3,d1
lsr.l #2,d1
subq.l #1,d1
encryptloop:
move.l (a0),d2
eor.l d0,d2
move.l d2,(a0)+
dbf d1,encryptloop
move.l (a7)+,d2
rts
#endasm